#ifndef DxCoroutine_H
#define DxCoroutine_H
#include <tuple>
#include <any>
#include <memory>
#include <vector>
#include "ccoroutine_core_global.h"
#include "awaiters.h"
namespace CCoroutine{
class PromiseBase;



//控制器的基类
class CCoroutine_EXPORT ControllerBase
{
public:
    ControllerBase();
    ControllerBase(const ControllerBase& o) = delete;
    ControllerBase(ControllerBase&& o);

    ControllerBase& operator = (ControllerBase&& other);

    void set_promise(PromiseBase* p);
protected:
    PromiseBase *base = nullptr;
};

//协程的基类
class CCoroutine_EXPORT PromiseBase
{
public:
    enum Status{
        Running,//运行态
        Suspended,//挂起态
        Finished,//结束态
    };


    PromiseBase(){

    }



    virtual ~PromiseBase(){

    }

    bool suspend(AwaiterBase* base,int num);

    virtual AwaiterBase* final_suspend();

    Status status();

    void resume();

    virtual void run() = 0;

protected:
    int pos = 0;
    std::unique_ptr<AwaiterBase> awaiter;
    Status m_status = Running;
};

//具备参数的协程
template<typename ...Args>
class ArgedPromise:public PromiseBase
{
public:
    ArgedPromise(){

    }

    void set_args(Args... args){
        this->args = {args...};
    }

protected:
    std::tuple<Args...> args;
};

template<typename T,typename ...Args>
typename T::Controller createCoro(Args... args){
    auto t = new T();
    t->set_args(args...);
    typename T::Controller ret;
    ret.set_promise(t);

    t->resume();

    return std::move(ret);
}
}
#define coro_begin void run() override{ \
switch(this->pos){ \
case 0: \
{if(!this->suspend(this->initial_suspend(),__LINE__))return;case __LINE__: \
this->awaiter->resume();}\

#define coro_return \
{if(!this->suspend(this->final_suspend(),__LINE__)) return;case __LINE__: \
this->awaiter->resume();this->m_status = PromiseBase::Finished;return;}

#define coro_return_value(value) \
{this->on_return_value(value);if(!this->suspend(this->final_suspend(),__LINE__)) return;case __LINE__: \
this->awaiter->resume();this->m_status = PromiseBase::Finished;return;}

#define coro_end coro_return}}

#define coro_yield(value) \
{if(!suspend(this->on_yield(value),__LINE__))return;case __LINE__: \
this->awaiter->resume();}

#define coro_await(a) \
{if(!this->suspend(getAwaiter(a),__LINE__)) return;case __LINE__: \
this->awaiter->resume();}

#define async_for_begin(gen) \
    while(true){ \
        coro_await(gen.next()); \
        if(gen.finished()) break;

#define async_for_end }

#endif
